package cn.icanci.loopstack.rec.spi.event;

import java.util.*;
import java.util.concurrent.*;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

/**
 * 事件分发抽象处理器
 * 
 * @author icanci
 * @since 1.0 Created in 2022/11/11 18:01
 */
public abstract class AbstractEventDispatcher implements EventDispatcher, ApplicationContextAware {
    /**
     * Spring 容器
     */
    protected ApplicationContext                     applicationContext;
    /**
     * 事件监听器列表
     */
    protected Map<Class<?>, List<BaseEventListener>> eventListMap        = new ConcurrentHashMap<>();
    /**
     * 监听器
     */
    protected List<BaseEventListener>                listeners           = new LinkedList();
    /**
     * 注册事件类型
     */
    protected Set<Class<?>>                          eventClasses        = new HashSet<>();
    /**
     * 排序器
     */
    protected static final ListenerComparator        LISTENER_COMPARATOR = new ListenerComparator();
    /**
     * 线程池核心大小
     */
    private static final int                         CORE_SIZE           = Runtime.getRuntime().availableProcessors();
    /**
     * 线程池
     */
    protected static final ThreadPoolExecutor        eventPool           = new ThreadPoolExecutor(CORE_SIZE,          //
        CORE_SIZE << 1,                                                                                               //
        60L,                                                                                                          //
        TimeUnit.SECONDS,                                                                                             //
        new LinkedBlockingQueue<>(2000),                                                                              //
        runnable -> new Thread(runnable, "AbstractEventDispatcher Pool-" + runnable.hashCode()),                      //
        (r, executor) -> {
            throw new RuntimeException("AbstractEventDispatcher Pool is EXHAUSTED!");
        });

    private final Object                             lock                = new Object();

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        synchronized (lock) {
            register();
        }
    }

    /**
     * 注册事件和监听器
     */
    protected abstract void register();

    /**
     * 获取事件执行线程池
     *
     * @return 事件执行线程池
     */
    protected Executor getTaskPool() {
        return eventPool;
    }
}
